package com.doit.day02

import scala.io.Source

/**
 * 需求：
 * 1.求每部电影的平均分，按照降序输出
 * 2.求每个用户评过电影的总数，按照降序排列
 * 3.每个用户评分的前三部电影(用户，电影信息，评分值)
 * 4.哪些年份的电影评分(平均分)最高，取最高的前五个年份
 */
object MovieDemo {
  def main(args: Array[String]): Unit = {
    /*
    1.求每部电影的平均分，按照降序输出
          1.读取文件，用三个类，分别代表 movie，rating，user
          2.将每一行的数据转换成 ==》对象
          3.将电影放在key，所有的评分封装在集合中，然后以map的形式展现
          4.求每部电影的平均分
     */

    //读文件
    val movie: List[String] = Source.fromFile("C:\\Users\\yi\\Desktop\\scala\\movies.txt").getLines().toList
    val rating: List[String] = Source.fromFile("C:\\Users\\yi\\Desktop\\scala\\ratings.txt").getLines().toList
    val user: List[String] = Source.fromFile("C:\\Users\\yi\\Desktop\\scala\\users.txt").getLines().toList


    //2.将每一行的数据转换成 ==》对象
    //movie
      val movie_info: List[Movie] = movie.map(line => {
        ////1_Toy Story (1995)_Animation|Children's|Comedy
        var movie_id: String = ""
        var movie_name: String =""
        var movie_type: String =""

        try{
          val arr: Array[String] = line.split("_")
          movie_id = arr(0)
          movie_name = arr(1)
          movie_type = arr(2)
        }catch{
          case e:Exception => println(e)
        }
        Movie(movie_id, movie_name, movie_type)
      })

   //转换将list集合中的movie对象转换成元组(map)  key movie_id，value 就是movie对象
   val movie_id_name: Map[String, Movie] = movie_info.map(movie => {
     (movie.movie_id, movie)
   }).toMap



      //user
/*      val user_info: List[Movie_User] = user.map(line => {
        var user_id: String = ""
        var gender: String = ""
        var age: Int = 0
        var job: String = ""
        var code: String = ""
        //1_F_16_10_48067
        //user_id:String,gender:String,age:Int,Job:String,code:String
        try {
          val arr: Array[String] = line.split("_")
          user_id = arr(0)
          gender = arr(1)
          age = arr(2).toInt
          job = arr(3)
          code = arr(4)
        } catch {
          case e: Exception => println(e)
        }
        Movie_User(user_id, gender, age, job, code)
      })*/

    //rating
    val rating_info: List[Rating] = rating.map(line => {
      var user_id: String = ""
      var movie_id: String = ""
      var rating: Double = 0
      var timeStamp: String = ""
      val arr: Array[String] = line.split("_")
      try {
        ////1_1193_5_978300760
        user_id = arr(0)
        movie_id = arr(1)
        rating = arr(2).toDouble
        timeStamp = arr(3)
      } catch {
        case e: Exception => println(e)
      }
      Rating(user_id, movie_id, rating, timeStamp)
    })

    //3.将电影放在key，所有的评分封装在集合中，然后以map的形式展现
    val movieIdAndRating: List[(String, Double)] = rating_info.map(rat => {
      (rat.movie_id, rat.rating)
    }) //==>(001,5),(001,3),(002,3)

    //对movie_id进行分组
    val map: Map[String, List[(String, Double)]] = movieIdAndRating.groupBy(_._1)


    //(001,list(1,2,3,2,3,2))
    val movieIdAndListRating: Map[String, List[Double]] = map.map(tp => {
      val movie_id: String = tp._1
      val list: List[(String, Double)] = tp._2
      //将list集合中的每一个元组全部映射成评分
      val listRating: List[Double] = list.map(_._2)
      (movie_id, listRating)
    })

    //求电影分数的平均值
    val movieIdAndAvgRating: Map[String, Double] = movieIdAndListRating.map(tp => {
      val movie_id: String = tp._1
      val list: List[Double] = tp._2
      //总分
      val ratingSum: Double = list.sum
      //总个数
      val count: Int = list.size
      //求平均分，并且转换成了保留小数点后2为
      val avgRating: Double = (ratingSum / count).formatted("%.2f").toDouble
      (movie_id, avgRating)
    })

    //按照降序进行输出
    val list: List[(String, Double)] = movieIdAndAvgRating.toList

    //    list.sortBy(-_._2)
    val res: List[(String, Double)] = list.sortWith((tp1, tp2) => {
      val thisRating: Double = tp1._2
      val thatRating: Double = tp2._2
      thisRating > thatRating
    })

    //想把movie_id转换成movie_name   ==> join案例
    val res1: List[(String, Double)] = res.map(tp => {
      var tuple: (String, Double) =  null

      val movie_id: String = tp._1
      val avg: Double = tp._2
      //这边可以获取到movie对象
      val flag: Boolean = movie_id_name.contains(movie_id)
      //如果flag是false的时候
      if (flag) {
        //得到电影的详细信息，就可以获取到了movie_name
        val movie: Movie = movie_id_name.get(movie_id).get
        tuple = (movie.movie_name, avg)
      }
        tuple
    }).filter(tp=>tp!=null)

    res1.foreach(println)


  }
}

//1_Toy Story (1995)_Animation|Children's|Comedy
case class Movie(movie_id: String, movie_name: String, movie_type: String)

//1_F_16_10_48067
case class Movie_User(user_id: String, gender: String, age: Int, job: String, code: String)

//1_1193_5_978300760
case class Rating(user_id: String, movie_id: String, rating: Double, timeStamp: String)